package com.easy.secret.service.impl;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import com.easy.secret.annotation.SecureField;
import com.easy.secret.config.SecureProperties;
import com.easy.secret.enums.SecureOperType;
import com.easy.secret.service.SecureService;
import com.easy.secret.utils.SecureUtils;

/**
 * @ProjectName: esay-secret-server
 * @Package: com.easy.secret.service.impl
 * @ClassName: EntitySecureService
 * @Description: java类作用描述
 * @Author: wangjc
 * @CreateDate: 2023/11/17
 * @UpdateUser: wangjc
 * @UpdateDate: 2023/11/17
 * @UpdateRemark: 更新内容
 * @Version: 1.0
 */
@Component
@ConditionalOnProperty(
        name = {"sm.flag"},
        havingValue = "true"
)
@EnableConfigurationProperties({SecureProperties.class})
public class EntitySecureService implements SecureService {

    @Autowired
    private SecureProperties properties;

    @Override
    public <T> T decrypt(T entityObj) throws IllegalAccessException {
        return transSecureObj(entityObj, SecureOperType.DEC);
    }

    @Override
    public <T> T encrypt(T entityObj) throws IllegalAccessException {
        return transSecureObj(entityObj, SecureOperType.ENC);
    }

    /**
     * 转换保密字段
     *
     * @param entityObj
     * @param secureOperType
     * @param <T>
     * @return
     * @throws IllegalAccessException
     */
    private <T> T transSecureObj(T entityObj, SecureOperType secureOperType) throws IllegalAccessException {
        for (Field field : entityObj.getClass().getDeclaredFields()) {
            SecureField sf = (SecureField) field.getAnnotation(SecureField.class);
            if (!Objects.isNull(sf)) {
                field.setAccessible(true);
                Object valueObj = field.get(entityObj);
                if (field.getType() == String.class) {
                    String value = (String) valueObj;
                    if (!StringUtils.isBlank(value)) {
                        transStringVal(field, secureOperType, entityObj, value);
                    }
                } else if (field.getType() == Date.class) {
                    transDateVal(field, secureOperType, entityObj, valueObj);
                }
            }
        }

        return entityObj;
    }

    /**
     * 转换字段值-日期类型
     * @param field             实体类的属性字段
     * @param secureOperType    操作类型（加解密）
     * @param entityObj         实体对象
     * @param valueObj          字段的属性值
     */
    private void transDateVal(Field field, SecureOperType secureOperType, Object entityObj, Object valueObj) {
        try {
            if(secureOperType.getCode().equals(SecureOperType.ENC.getCode())) {
                // 加密
                field.set(entityObj, SecureUtils.getInstance(properties).encryptDate((Date) valueObj));
            } else {
                // 解密
                field.set(entityObj, SecureUtils.getInstance(properties).decryptDate((String) valueObj));
            }
        } catch (IllegalAccessException e){
            e.printStackTrace();
        }
    }

    /**
     * 转换字段值 - 字段类型字符串
     * @param field
     * @param secureOperType
     * @param entityObj
     * @param value
     */
    private void transStringVal(Field field, SecureOperType secureOperType, Object entityObj, String value) {
        try {
            if(secureOperType.getCode().equals(SecureOperType.ENC.getCode())) {
                // 加密
                field.set(entityObj, SecureUtils.getInstance(properties).encrypt(value));
            } else {
                // 解密
                field.set(entityObj, SecureUtils.getInstance(properties).decrypt(value));
            }
        } catch (IllegalAccessException e){
            e.printStackTrace();
        }
    }
}
